/**
 * Ingenius-Group S.A.S
 *
 * Project: SAU
 * File: AppController.java
 * Date: 20/01/2011
 */

package com.ingenius.sau.client;

import java.util.HashMap;
import java.util.Map;

import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.MessageBoxEvent;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.RootPanel;
import com.ingenius.sau.client.event.EditAcademicProgramEvent;
import com.ingenius.sau.client.event.EditAcademicProgramEvent.EditAcademicProgramEventHandler;
import com.ingenius.sau.client.event.EditAssignedInstrumentEvent;
import com.ingenius.sau.client.event.EditAssignedInstrumentEvent.EditAssignedInstrumentEventHandler;
import com.ingenius.sau.client.event.EditDocumentEvent;
import com.ingenius.sau.client.event.EditDocumentEvent.EditDocumentEventHandler;
import com.ingenius.sau.client.event.EditFactor2EvaluateEvent;
import com.ingenius.sau.client.event.EditFactor2EvaluateEvent.EditFactor2EvaluateEventHandler;
import com.ingenius.sau.client.event.EditFactorEvent;
import com.ingenius.sau.client.event.EditFactorEvent.EditFactorEventHandler;
import com.ingenius.sau.client.event.EditFeature2EvaluateEvent;
import com.ingenius.sau.client.event.EditFeature2EvaluateEvent.EditFeature2EvaluateEventHandler;
import com.ingenius.sau.client.event.EditFeatureEvent;
import com.ingenius.sau.client.event.EditFeatureEvent.EditFeatureEventHandler;
import com.ingenius.sau.client.event.EditGroupEvent;
import com.ingenius.sau.client.event.EditGroupEvent.EditGroupEventHandler;
import com.ingenius.sau.client.event.EditGuidelineEvent;
import com.ingenius.sau.client.event.EditGuidelineEvent.EditGuidelineEventHandler;
import com.ingenius.sau.client.event.EditIndicator2EvaluateEvent;
import com.ingenius.sau.client.event.EditIndicator2EvaluateEvent.EditIndicator2EvaluateEventHandler;
import com.ingenius.sau.client.event.EditIndicatorEvent;
import com.ingenius.sau.client.event.EditIndicatorEvent.EditIndicatorEventHandler;
import com.ingenius.sau.client.event.EditQuestionEvent;
import com.ingenius.sau.client.event.EditQuestionEvent.EditQuestionEventHandler;
import com.ingenius.sau.client.event.EditRoleEvent;
import com.ingenius.sau.client.event.EditRoleEvent.EditRoleEventHandler;
import com.ingenius.sau.client.event.EditSelfEvaluationEvent;
import com.ingenius.sau.client.event.EditSelfEvaluationEvent.EditSelfEvaluationEventHandler;
import com.ingenius.sau.client.event.EditUserEvent;
import com.ingenius.sau.client.event.EditUserEvent.EditUserEventHandler;
import com.ingenius.sau.client.event.ListAcademicProgramsEvent;
import com.ingenius.sau.client.event.ListAcademicProgramsEvent.ListAcademicProgramsEventHandler;
import com.ingenius.sau.client.event.ListAssignedInstrumentsEvent;
import com.ingenius.sau.client.event.ListAssignedInstrumentsEvent.ListAssignedInstrumentsEventHandler;
import com.ingenius.sau.client.event.ListDocumentsEvent;
import com.ingenius.sau.client.event.ListDocumentsEvent.ListDocumentsEventHandler;
import com.ingenius.sau.client.event.ListFactors2EvaluateEvent;
import com.ingenius.sau.client.event.ListFactors2EvaluateEvent.ListFactors2EvaluateEventHandler;
import com.ingenius.sau.client.event.ListFactorsEvent;
import com.ingenius.sau.client.event.ListFactorsEvent.ListFactorsEventHandler;
import com.ingenius.sau.client.event.ListFeatures2EvaluateEvent;
import com.ingenius.sau.client.event.ListFeatures2EvaluateEvent.ListFeatures2EvaluateEventHandler;
import com.ingenius.sau.client.event.ListFeaturesEvent;
import com.ingenius.sau.client.event.ListFeaturesEvent.ListFeaturesEventHandler;
import com.ingenius.sau.client.event.ListGroupsEvent;
import com.ingenius.sau.client.event.ListGroupsEvent.ListGroupsEventHandler;
import com.ingenius.sau.client.event.ListGuidelinesEvent;
import com.ingenius.sau.client.event.ListGuidelinesEvent.ListGuidelinesEventHandler;
import com.ingenius.sau.client.event.ListIndicators2EvaluateEvent;
import com.ingenius.sau.client.event.ListIndicators2EvaluateEvent.ListIndicators2EvaluateEventHandler;
import com.ingenius.sau.client.event.ListIndicatorsEvent;
import com.ingenius.sau.client.event.ListIndicatorsEvent.ListIndicatorsEventHandler;
import com.ingenius.sau.client.event.ListQuestionsEvent;
import com.ingenius.sau.client.event.ListQuestionsEvent.ListQuestionsEventHandler;
import com.ingenius.sau.client.event.ListRolesEvent;
import com.ingenius.sau.client.event.ListRolesEvent.ListRolesEventHandler;
import com.ingenius.sau.client.event.ListSelfEvaluationsEvent;
import com.ingenius.sau.client.event.ListSelfEvaluationsEvent.ListSelfEvaluationsEventHandler;
import com.ingenius.sau.client.event.ListUsersEvent;
import com.ingenius.sau.client.event.ListUsersEvent.ListUsersEventHandler;
import com.ingenius.sau.client.presenter.EditAcademicProgramPresenter;
import com.ingenius.sau.client.presenter.EditAssignedInstrumentPresenter;
import com.ingenius.sau.client.presenter.EditDocumentPresenter;
import com.ingenius.sau.client.presenter.EditFactor2EvaluatePresenter;
import com.ingenius.sau.client.presenter.EditFactorPresenter;
import com.ingenius.sau.client.presenter.EditFeature2EvaluatePresenter;
import com.ingenius.sau.client.presenter.EditFeaturePresenter;
import com.ingenius.sau.client.presenter.EditGroupPresenter;
import com.ingenius.sau.client.presenter.EditGuidelinePresenter;
import com.ingenius.sau.client.presenter.EditIndicator2EvaluatePresenter;
import com.ingenius.sau.client.presenter.EditIndicatorPresenter;
import com.ingenius.sau.client.presenter.EditQuestionPresenter;
import com.ingenius.sau.client.presenter.EditRolePresenter;
import com.ingenius.sau.client.presenter.EditSelfEvaluationPresenter;
import com.ingenius.sau.client.presenter.EditUserPresenter;
import com.ingenius.sau.client.presenter.ListAcademicProgramsPresenter;
import com.ingenius.sau.client.presenter.ListAssignedInstrumentsPresenter;
import com.ingenius.sau.client.presenter.ListDocumentsPresenter;
import com.ingenius.sau.client.presenter.ListFactors2EvaluatePresenter;
import com.ingenius.sau.client.presenter.ListFactorsPresenter;
import com.ingenius.sau.client.presenter.ListFeatures2EvaluatePresenter;
import com.ingenius.sau.client.presenter.ListFeaturesPresenter;
import com.ingenius.sau.client.presenter.ListGroupsPresenter;
import com.ingenius.sau.client.presenter.ListGuidelinesPresenter;
import com.ingenius.sau.client.presenter.ListIndicators2EvaluatePresenter;
import com.ingenius.sau.client.presenter.ListIndicatorsPresenter;
import com.ingenius.sau.client.presenter.ListQuestionsPresenter;
import com.ingenius.sau.client.presenter.ListRolesPresenter;
import com.ingenius.sau.client.presenter.ListSelfEvaluationsPresenter;
import com.ingenius.sau.client.presenter.ListUsersPresenter;
import com.ingenius.sau.client.presenter.Presenter;
import com.ingenius.sau.client.service.CoreServiceAsync;
import com.ingenius.sau.client.service.GuidelinesServiceAsync;
import com.ingenius.sau.client.service.InstrumentsServiceAsync;
import com.ingenius.sau.client.service.UsersService;
import com.ingenius.sau.client.service.UsersServiceAsync;
import com.ingenius.sau.client.view.EditAcademicProgramView;
import com.ingenius.sau.client.view.EditAssignedInstrumentView;
import com.ingenius.sau.client.view.EditDocumentView;
import com.ingenius.sau.client.view.EditFactor2EvaluateView;
import com.ingenius.sau.client.view.EditFactorView;
import com.ingenius.sau.client.view.EditFeature2EvaluateView;
import com.ingenius.sau.client.view.EditFeatureView;
import com.ingenius.sau.client.view.EditGroupView;
import com.ingenius.sau.client.view.EditGuidelineView;
import com.ingenius.sau.client.view.EditIndicator2EvaluateView;
import com.ingenius.sau.client.view.EditIndicatorView;
import com.ingenius.sau.client.view.EditQuestionView;
import com.ingenius.sau.client.view.EditRoleView;
import com.ingenius.sau.client.view.EditSelfEvaluationView;
import com.ingenius.sau.client.view.EditUserView;
import com.ingenius.sau.client.view.ListAcademicProgramsView;
import com.ingenius.sau.client.view.ListAssignedInstrumentsView;
import com.ingenius.sau.client.view.ListDocumentsView;
import com.ingenius.sau.client.view.ListFactors2EvaluateView;
import com.ingenius.sau.client.view.ListFactorsView;
import com.ingenius.sau.client.view.ListFeatures2EvaluateView;
import com.ingenius.sau.client.view.ListFeaturesView;
import com.ingenius.sau.client.view.ListGroupsView;
import com.ingenius.sau.client.view.ListGuidelinesView;
import com.ingenius.sau.client.view.ListIndicators2EvaluateView;
import com.ingenius.sau.client.view.ListIndicatorsView;
import com.ingenius.sau.client.view.ListQuestionsView;
import com.ingenius.sau.client.view.ListRolesView;
import com.ingenius.sau.client.view.ListSelfEvaluationsView;
import com.ingenius.sau.client.view.ListUsersView;
import com.ingenius.sau.client.view.widgets.TabMenu;

/**
 * Class <strong>AppController</strong>
 * 
 * @author Jesus David
 * @version 0.1
 */
public class AppController implements Presenter, ValueChangeHandler<String> {

	// UTILITY
	private static Map<String, Object> attributes = new HashMap<String, Object>();

	// DATA
	private TabMenu menu;
	private HasWidgets container;
	private final HandlerManager eventBus;

	// RPC services
	private final CoreServiceAsync rpcCoreService;
	private final GuidelinesServiceAsync rpcGuidelinesService;
	private final InstrumentsServiceAsync rpcInstrumentsService;
	private final UsersServiceAsync rpcUsersService;

	// CONSTRUCTOR
	public AppController(HandlerManager eventBus,
			CoreServiceAsync rpcCoreService,
			GuidelinesServiceAsync rpcGuidelinesService,
			InstrumentsServiceAsync rpcInstrumentsService,
			UsersServiceAsync rpcUsersService) {

		History.addValueChangeHandler(this);

		this.eventBus = eventBus;
		this.rpcCoreService = rpcCoreService;
		this.rpcGuidelinesService = rpcGuidelinesService;
		this.rpcInstrumentsService = rpcInstrumentsService;
		this.rpcUsersService = rpcUsersService;

		createMenu();
		registerCoreModuleEvents();
		registerGuidelineModuleEvents();
		registerInstrumentModuleEvents();
		registerUserModuleEvents();
		hideStatusMessage();

		String userID = Cookies.getCookie(Constants.COOKIE_USER_ID);
		String html = "<a>" + userID + "</a>";
		RootPanel.get("current-user").add(new HTML(html));
		System.out.println("Client --> UserID: " + userID);
	}

	private void createMenu() {
		menu = new TabMenu();
		// TODO i18n
		menu.addItem("Home", Constants.TOKEN_HOME);
		menu.addItem("Guidelines", Constants.TOKEN_GUIDELINES);
		menu.addItem("Programs", Constants.TOKEN_PROGRAMS);
		menu.addItem("Processes", Constants.TOKEN_PROCESSES);
		menu.addItem("Instruments", Constants.TOKEN_DOCUMENTS);
		menu.addItem("Users", Constants.TOKEN_USERS);
		RootPanel.get("menu").add(menu);
	}

	private void registerCoreModuleEvents() {
		eventBus.addHandler(ListAcademicProgramsEvent.TYPE,
				new ListAcademicProgramsEventHandler() {
					@Override
					public void onListAcademicPrograms(
							ListAcademicProgramsEvent event) {
						goListAcademicPrograms();
					}
				});

		eventBus.addHandler(EditAcademicProgramEvent.TYPE,
				new EditAcademicProgramEventHandler() {
					@Override
					public void onEditAcademicProgram(
							EditAcademicProgramEvent event) {
						goEditAcademicProgram(event.getAcademicProgramId());
					}
				});

		eventBus.addHandler(ListSelfEvaluationsEvent.TYPE,
				new ListSelfEvaluationsEventHandler() {
					@Override
					public void onListSelfEvaluations(
							ListSelfEvaluationsEvent event) {
						goListSelfEvaluations();
					}
				});

		eventBus.addHandler(EditSelfEvaluationEvent.TYPE,
				new EditSelfEvaluationEventHandler() {
					@Override
					public void onEditSelfEvaluation(
							EditSelfEvaluationEvent event) {
						goEditSelfEvaluation(event.getSelfEvaluationId());
					}
				});

		eventBus.addHandler(ListFactors2EvaluateEvent.TYPE,
				new ListFactors2EvaluateEventHandler() {
					@Override
					public void onListFactors2Evaluate(
							ListFactors2EvaluateEvent event) {
						goListFactors2Evaluate();
					}
				});

		eventBus.addHandler(EditFactor2EvaluateEvent.TYPE,
				new EditFactor2EvaluateEventHandler() {
					@Override
					public void onEditFactor2Evaluate(
							EditFactor2EvaluateEvent event) {
						goEditFactor2Evaluate(event.getFactot2EvaluateId());
					}
				});

		eventBus.addHandler(ListFeatures2EvaluateEvent.TYPE,
				new ListFeatures2EvaluateEventHandler() {
					@Override
					public void onListFeatures2Evaluate(
							ListFeatures2EvaluateEvent event) {
						goListFeatures2Evaluate();
					}
				});

		eventBus.addHandler(EditFeature2EvaluateEvent.TYPE,
				new EditFeature2EvaluateEventHandler() {
					@Override
					public void onEditFeature2Evaluate(
							EditFeature2EvaluateEvent event) {
						goEditFeature2Evaluate(event.getFeature2EvaluateId());
					}
				});

		eventBus.addHandler(ListIndicators2EvaluateEvent.TYPE,
				new ListIndicators2EvaluateEventHandler() {
					@Override
					public void onListIndicators2Evaluate(
							ListIndicators2EvaluateEvent event) {
						goListIndicators2Evaluate();
					}
				});

		eventBus.addHandler(EditIndicator2EvaluateEvent.TYPE,
				new EditIndicator2EvaluateEventHandler() {
					@Override
					public void onEditIndicator2Evaluate(
							EditIndicator2EvaluateEvent event) {
						goEditIndicator2Evaluate(event
								.getIndicator2EvaluateId());
					}
				});

		eventBus.addHandler(ListAssignedInstrumentsEvent.TYPE,
				new ListAssignedInstrumentsEventHandler() {
					@Override
					public void onListAssignedInstruments(
							ListAssignedInstrumentsEvent event) {
						goListAssignedInstruments();
					}
				});

		eventBus.addHandler(EditAssignedInstrumentEvent.TYPE,
				new EditAssignedInstrumentEventHandler() {
					@Override
					public void onEditAssignedInstrument(
							EditAssignedInstrumentEvent event) {
						goEditAssignedInstrument(event
								.getAssignedInstrumentId());
					}
				});

	}

	private void registerGuidelineModuleEvents() {
		eventBus.addHandler(ListGuidelinesEvent.TYPE,
				new ListGuidelinesEventHandler() {
					@Override
					public void onListGuidelines(ListGuidelinesEvent event) {
						goListGuidelines();
					}
				});

		eventBus.addHandler(EditGuidelineEvent.TYPE,
				new EditGuidelineEventHandler() {
					@Override
					public void onEditGuideline(EditGuidelineEvent event) {
						goEditGuideline(event.getGuidelineId());
					}
				});

		eventBus.addHandler(ListFactorsEvent.TYPE,
				new ListFactorsEventHandler() {
					@Override
					public void onListFactors(ListFactorsEvent event) {
						goListFactors();
					}
				});

		eventBus.addHandler(EditFactorEvent.TYPE, new EditFactorEventHandler() {
			@Override
			public void onEditFactor(EditFactorEvent event) {
				goEditFactor(event.getFactorId());
			}
		});

		eventBus.addHandler(ListFeaturesEvent.TYPE,
				new ListFeaturesEventHandler() {
					@Override
					public void onListFeatures(ListFeaturesEvent event) {
						goListFeatures();
					}
				});

		eventBus.addHandler(EditFeatureEvent.TYPE,
				new EditFeatureEventHandler() {
					@Override
					public void onEditFeature(EditFeatureEvent event) {
						goEditFeature(event.getFeatureId());
					}
				});

		eventBus.addHandler(ListIndicatorsEvent.TYPE,
				new ListIndicatorsEventHandler() {
					@Override
					public void onListIndicators(ListIndicatorsEvent event) {
						goListIndicators();
					}
				});

		eventBus.addHandler(EditIndicatorEvent.TYPE,
				new EditIndicatorEventHandler() {
					@Override
					public void onEditIndicator(EditIndicatorEvent event) {
						goEditIndicator(event.getIndicatorId());
					}
				});

	}

	private void registerInstrumentModuleEvents() {
		eventBus.addHandler(ListDocumentsEvent.TYPE,
				new ListDocumentsEventHandler() {
					@Override
					public void onListDocuments(ListDocumentsEvent event) {
						goListDocuments();
					}
				});

		eventBus.addHandler(EditDocumentEvent.TYPE,
				new EditDocumentEventHandler() {
					@Override
					public void onEditDocument(EditDocumentEvent event) {
						goEditDocument(event.getDocumentId());
					}
				});
		eventBus.addHandler(ListQuestionsEvent.TYPE,
				new ListQuestionsEventHandler() {
					@Override
					public void onListQuestions(ListQuestionsEvent event) {
						goListQuestions();
					}
				});

		eventBus.addHandler(EditQuestionEvent.TYPE,
				new EditQuestionEventHandler() {
					@Override
					public void onEditQuestion(EditQuestionEvent event) {
						goEditQuestion(event.getQuestionId());
					}
				});
	}

	private void registerUserModuleEvents() {
		eventBus.addHandler(ListUsersEvent.TYPE, new ListUsersEventHandler() {
			@Override
			public void onListUsers(ListUsersEvent event) {
				goListUsers();
			}
		});

		eventBus.addHandler(EditUserEvent.TYPE, new EditUserEventHandler() {
			@Override
			public void onEditUser(EditUserEvent event) {
				goEditUser(event.getUserId());
			}
		});

		eventBus.addHandler(ListRolesEvent.TYPE, new ListRolesEventHandler() {
			@Override
			public void onListRoles(ListRolesEvent event) {
				goListRoles();
			}
		});

		eventBus.addHandler(EditRoleEvent.TYPE, new EditRoleEventHandler() {
			@Override
			public void onEditRole(EditRoleEvent event) {
				goEditRole(event.getRoleId());
			}
		});

		eventBus.addHandler(ListGroupsEvent.TYPE, new ListGroupsEventHandler() {
			@Override
			public void onListGroups(ListGroupsEvent event) {
				goListGroups();
			}
		});

		eventBus.addHandler(EditGroupEvent.TYPE, new EditGroupEventHandler() {
			@Override
			public void onEditGroup(EditGroupEvent event) {
				goEditGroup(event.getGroupId());
			}
		});
	}

	@Override
	public void go(HasWidgets container) {
		this.container = container;
		if ("".equals(History.getToken())) {
			History.newItem(Constants.TOKEN_HOME);

		} else {
			History.fireCurrentHistoryState();
		}
	}

	@Override
	public void onValueChange(ValueChangeEvent<String> event) {
		String currentToken = event.getValue();

		if (Constants.TOKEN_HOME.equals(currentToken)) {
			goHome();

		} else if (Constants.TOKEN_GUIDELINES.equals(currentToken)) {
			goListGuidelines();

		} else if (Constants.TOKEN_PROGRAMS.equals(currentToken)) {
			goListAcademicPrograms();

		} else if (Constants.TOKEN_PROCESSES.equals(currentToken)) {
			goListSelfEvaluations();

		} else if (Constants.TOKEN_DOCUMENTS.equals(currentToken)) {
			goListDocuments();

		} else if (Constants.TOKEN_QUESTIONS.equals(currentToken)) {
			goListQuestions();

		} else if (Constants.TOKEN_USERS.equals(currentToken)) {
			goListUsers();

		} else if (Constants.TOKEN_ROLES.equals(currentToken)) {
			goListRoles();

		} else if (Constants.TOKEN_GROUPS.equals(currentToken)) {
			goListGroups();

		}
		menu.setCurrent(currentToken);
	}

	public void goHome() {
		container.clear();
		container.add(new HTML("<img id='home-logo' src='"
				+ Constants.ICON_HOME
				+ "' onmousedown='event.preventDefault()'/>"));
	}

	public void goListUsers() {
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new ListUsersPresenter(eventBus, rpcUsersService,
						ListUsersView.getInstance()).go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_USERS, Constants.ACTION_READ, callback);
	}

	public void goEditUser(final String userId) {
		String action = (userId == null) ? Constants.ACTION_CREATE
				: Constants.ACTION_EDIT;
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new EditUserPresenter(eventBus, rpcUsersService,
						new EditUserView(), userId).go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_USERS, action, callback);
	}

	public void goListRoles() {
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new ListRolesPresenter(eventBus, rpcUsersService,
						ListRolesView.getInstance()).go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_USERS, Constants.ACTION_READ, callback);
	}

	public void goEditRole(final String roleId) {
		String action = (roleId == null) ? Constants.ACTION_CREATE
				: Constants.ACTION_EDIT;
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new EditRolePresenter(eventBus, rpcUsersService,
						new EditRoleView(), roleId).go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_USERS, action, callback);
	}

	public void goListGroups() {
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new ListGroupsPresenter(eventBus, rpcUsersService,
						ListGroupsView.getInstance()).go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_USERS, Constants.ACTION_READ, callback);
	}

	public void goEditGroup(final String groupId) {
		String action = (groupId == null) ? Constants.ACTION_CREATE
				: Constants.ACTION_EDIT;
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new EditGroupPresenter(eventBus, rpcUsersService,
						new EditGroupView(), groupId).go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_USERS, action, callback);
	}

	public void goListGuidelines() {
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new ListGuidelinesPresenter(eventBus, rpcGuidelinesService,
						ListGuidelinesView.getInstance()).go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_GUIDELINES, Constants.ACTION_READ,
				callback);
	}

	public void goEditGuideline(final String guidelineId) {
		String action = (guidelineId == null) ? Constants.ACTION_CREATE
				: Constants.ACTION_EDIT;
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new EditGuidelinePresenter(eventBus, rpcGuidelinesService,
						new EditGuidelineView(), guidelineId).go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_GUIDELINES, action, callback);
	}

	public void goListFactors() {
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new ListFactorsPresenter(eventBus, rpcGuidelinesService,
						ListFactorsView.getInstance()).go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_GUIDELINES, Constants.ACTION_READ,
				callback);
	}

	public void goEditFactor(final String factorId) {
		String action = (factorId == null) ? Constants.ACTION_CREATE
				: Constants.ACTION_EDIT;
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new EditFactorPresenter(eventBus, rpcGuidelinesService,
						new EditFactorView(), factorId).go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_GUIDELINES, action, callback);
	}

	public void goListFeatures() {
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new ListFeaturesPresenter(eventBus, rpcGuidelinesService,
						ListFeaturesView.getInstance()).go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_GUIDELINES, Constants.ACTION_READ,
				callback);
	}

	public void goEditFeature(final String featureId) {
		String action = (featureId == null) ? Constants.ACTION_CREATE
				: Constants.ACTION_EDIT;
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new EditFeaturePresenter(eventBus, rpcGuidelinesService,
						new EditFeatureView(), featureId).go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_GUIDELINES, action, callback);
	}

	public void goListIndicators() {
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new ListIndicatorsPresenter(eventBus, rpcGuidelinesService,
						ListIndicatorsView.getInstance()).go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_GUIDELINES, Constants.ACTION_READ,
				callback);
	}

	public void goEditIndicator(final String indicatorId) {
		String action = (indicatorId == null) ? Constants.ACTION_CREATE
				: Constants.ACTION_EDIT;
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new EditIndicatorPresenter(eventBus, rpcGuidelinesService,
						new EditIndicatorView(), indicatorId).go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_GUIDELINES, action, callback);
	}

	public void goListAcademicPrograms() {
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new ListAcademicProgramsPresenter(eventBus, rpcCoreService,
						ListAcademicProgramsView.getInstance()).go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_PROGRAMS, Constants.ACTION_READ,
				callback);
	}

	public void goEditAcademicProgram(final String programId) {
		String action = (programId == null) ? Constants.ACTION_CREATE
				: Constants.ACTION_EDIT;
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new EditAcademicProgramPresenter(eventBus, rpcCoreService,
						new EditAcademicProgramView(), programId).go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_PROGRAMS, action, callback);
	}

	public void goListSelfEvaluations() {
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new ListSelfEvaluationsPresenter(eventBus, rpcCoreService,
						ListSelfEvaluationsView.getInstance()).go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_PROCESSES, Constants.ACTION_READ,
				callback);
	}

	public void goEditSelfEvaluation(final String evaluationId) {
		String action = (evaluationId == null) ? Constants.ACTION_CREATE
				: Constants.ACTION_EDIT;
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new EditSelfEvaluationPresenter(eventBus, rpcCoreService,
						new EditSelfEvaluationView(), evaluationId)
						.go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_PROCESSES, action, callback);
	}

	public void goListFactors2Evaluate() {
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new ListFactors2EvaluatePresenter(eventBus, rpcCoreService,
						ListFactors2EvaluateView.getInstance()).go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_PROCESSES, Constants.ACTION_READ,
				callback);
	}

	public void goEditFactor2Evaluate(final String factor2EvaluateId) {
		String action = (factor2EvaluateId == null) ? Constants.ACTION_CREATE
				: Constants.ACTION_EDIT;
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new EditFactor2EvaluatePresenter(eventBus, rpcCoreService,
						new EditFactor2EvaluateView(), factor2EvaluateId)
						.go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_PROCESSES, action, callback);
	}

	public void goListFeatures2Evaluate() {
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new ListFeatures2EvaluatePresenter(eventBus, rpcCoreService,
						ListFeatures2EvaluateView.getInstance()).go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_PROCESSES, Constants.ACTION_READ,
				callback);
	}

	public void goEditFeature2Evaluate(final String feature2EvaluateId) {
		String action = (feature2EvaluateId == null) ? Constants.ACTION_CREATE
				: Constants.ACTION_EDIT;
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new EditFeature2EvaluatePresenter(eventBus, rpcCoreService,
						new EditFeature2EvaluateView(), feature2EvaluateId)
						.go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_PROCESSES, action, callback);
	}

	public void goListIndicators2Evaluate() {
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new ListIndicators2EvaluatePresenter(eventBus, rpcCoreService,
						ListIndicators2EvaluateView.getInstance())
						.go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_PROCESSES, Constants.ACTION_READ,
				callback);
	}

	public void goEditIndicator2Evaluate(final String indicator2EvaluateId) {
		String action = (indicator2EvaluateId == null) ? Constants.ACTION_CREATE
				: Constants.ACTION_EDIT;
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new EditIndicator2EvaluatePresenter(eventBus, rpcCoreService,
						new EditIndicator2EvaluateView(), indicator2EvaluateId)
						.go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_PROCESSES, action, callback);
	}

	public void goListAssignedInstruments() {
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new ListAssignedInstrumentsPresenter(eventBus, rpcCoreService,
						ListAssignedInstrumentsView.getInstance())
						.go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_PROCESSES, Constants.ACTION_READ,
				callback);
	}

	public void goEditAssignedInstrument(final String assignedInstrumentId) {
		String action = (assignedInstrumentId == null) ? Constants.ACTION_CREATE
				: Constants.ACTION_EDIT;
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new EditAssignedInstrumentPresenter(eventBus, rpcCoreService,
						new EditAssignedInstrumentView(), assignedInstrumentId)
						.go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_PROCESSES, action, callback);
	}

	public void goListDocuments() {
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new ListDocumentsPresenter(eventBus, rpcInstrumentsService,
						ListDocumentsView.getInstance()).go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_INSTRUMENTS, Constants.ACTION_READ,
				callback);
	}

	public void goEditDocument(final String documentId) {
		String action = (documentId == null) ? Constants.ACTION_CREATE
				: Constants.ACTION_EDIT;
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new EditDocumentPresenter(eventBus, rpcInstrumentsService,
						new EditDocumentView(), documentId).go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_INSTRUMENTS, action, callback);
	}

	public void goListQuestions() {
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new ListQuestionsPresenter(eventBus, rpcInstrumentsService,
						ListQuestionsView.getInstance()).go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_INSTRUMENTS, Constants.ACTION_READ,
				callback);
	}

	public void goEditQuestion(final String questionId) {
		String action = (questionId == null) ? Constants.ACTION_CREATE
				: Constants.ACTION_EDIT;
		Callback callback = new Callback() {
			@Override
			public void excecute() {
				new EditQuestionPresenter(eventBus, rpcInstrumentsService,
						new EditQuestionView(), questionId).go(container);
			}
		};
		doWhitPermission(Constants.TOKEN_INSTRUMENTS, action, callback);
	}

	private static void showErrorMessage() {
		MessageBox box = new MessageBox();
		box.setIcon(MessageBox.ERROR);
		box.setButtons(MessageBox.OK);
		// TODO i18n
		box.setTitle("Access Denied");
		box.setMessage("You are not authorized to perform this action.");
		box.getDialog().setStyleAttribute("text-align", "justify");
		box.addCallback(new Listener<MessageBoxEvent>() {
			@Override
			public void handleEvent(MessageBoxEvent be) {
				if ("OK".equalsIgnoreCase(be.getButtonClicked().getText())) {
					History.newItem(Constants.TOKEN_HOME);
				}
			}
		});
		box.show();
	}

	public static void doWhitPermission(String module, String action,
			final Callback callback) {

		UsersServiceAsync service = GWT.create(UsersService.class);
		service.hasPermission(module, action, new AsyncCallback<Boolean>() {
			@Override
			public void onSuccess(Boolean result) {
				if (result != null && result == true) {
					callback.excecute();
				} else {
					onFailure(new Throwable("Forbidden"));
				}
			}

			@Override
			public void onFailure(Throwable caught) {
				showErrorMessage();
			}
		});
	}

	public static void setAttribute(String key, Object value) {
		attributes.put(key, value);
	}

	public static Object getAttribute(String key) {
		return attributes.get(key);
	}

	public static void setStatusMessage(String msg) {
		RootPanel.get("gwt-status").clear();
		RootPanel.get("gwt-status").setVisible(true);
		RootPanel.get("gwt-status").add(new HTML(msg));
	}

	public static void hideStatusMessage() {
		RootPanel.get("gwt-status").setVisible(false);
	}
}
